package com.hww.dtalk;

import android.util.Log;

import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池管理
 *
 * @author Com_PC
 */
public class ThreadPoolManager {

    private static volatile ThreadPoolManager threadPoolManager;

    public static ThreadPoolManager getInstance() {
        if (null == threadPoolManager) {
            synchronized (ThreadPoolManager.class) {
                if (null == threadPoolManager) {
                    threadPoolManager = new ThreadPoolManager();
                }
            }
        }
        return threadPoolManager;
    }

    public ThreadPoolManager() {
        getExecutorService();
    }

    /**
     * 核心线程池的数量，同时能够执行的线程数量
     */
    private int corePoolSize;
    /**
     * 最大线程池数量，表示当缓冲队列满的时候能继续容纳的等待任务的数量
     */
    private int maximumPoolSize;
    /**
     * 存活时间
     */
    private long keepAliveTime = 0;
    private TimeUnit unit = TimeUnit.MILLISECONDS;
    private ExecutorService executorService;


    private synchronized void getExecutorService() {
        /**
         * 给corePoolSize赋值：当前设备可用处理器核心数*2 + 1,能够让cpu的效率得到最大程度执行（有研究论证的）
         */
        corePoolSize = Runtime.getRuntime().availableProcessors();
        /*虽然maximumPoolSize用不到，但是需要赋值，否则报错*/
        /*maximumPoolSize = corePoolSize * 2 + 1;*/
        maximumPoolSize = corePoolSize;
        Log.i("hww", "faceLog pool   corePoolSize = " + corePoolSize + "   maximumPoolSize = " + maximumPoolSize);
        //线程工程，用于创建线程
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("dTalk-pool-%d").build();
        executorService = MoreExecutors.getExitingExecutorService(new ThreadPoolExecutor(
                /*核心线程数，一旦创建将不会再释放。
                如果创建的线程数还没有达到指定的核心线程数量，将会继续创建新的核心线程，直到达到最大核心线程数后，核心线程数将不在增加；
                如果没有空闲的核心线程，同时又未达到最大线程数，则将继续创建非核心线程；
                如果核心线程数等于最大线程数，则当核心线程都处于激活状态时，任务将被挂起，等待空闲线程来执行*/
                corePoolSize,
                //最大线程数，允许创建的最大线程数量。如果最大线程数等于核心线程数，则无法创建非核心线程；如果非核心线程处于空闲时，超过设置的空闲时间，则将被回收，释放占用的资源
                maximumPoolSize,
                //表示的是maximumPoolSize当中等待任务的存活时间    也就是当线程空闲时，所允许保存的最大时间，超过这个时间，线程将被释放销毁，但只针对于非核心线程
                keepAliveTime,
                //时间单位
                unit,
                //任务队列，存储暂时无法执行的任务，等待空闲线程来执行任务      缓冲队列，用于存放等待任务，Linked的先进先出
                new LinkedBlockingQueue<Runnable>(1024),
                threadFactory,
                /*用来对超出maximumPoolSize的任务的处理策略
                    1. CallerRunsPolicy ：这个策略重试添加当前的任务，他会自动重复调用 execute() 方法，直到成功。
                    2. AbortPolicy ：对拒绝任务抛弃处理，并且抛出异常。
                    3. DiscardPolicy ：对拒绝任务直接无声抛弃，没有异常信息。
                    4. DiscardOldestPolicy ：对拒绝任务不抛弃，而是抛弃队列里面等待最久的一个线程，然后把拒绝任务加到队列。*/
                new ThreadPoolExecutor.DiscardOldestPolicy()));
    }


    public synchronized ExecutorService getMoreExecutorService() {
        if (null == executorService) {
            getExecutorService();
        }
        return executorService;
    }

}
